package top.ffhome.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.ffhome.common.constant.CacheConstants;
import top.ffhome.common.constant.UserConstants;
import top.ffhome.common.core.mybatisplus.service.impl.BaseServiceImpl;
import top.ffhome.common.core.redis.RedisCache;
import top.ffhome.common.core.text.Convert;
import top.ffhome.common.utils.StringUtils;
import top.ffhome.system.domain.SysConfig;
import top.ffhome.system.mapper.SysConfigMapper;
import top.ffhome.system.service.ISysConfigService;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 参数配置 服务层实现
 *
 * @author ruoyi
 */
@Service
public class SysConfigServiceImpl extends BaseServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {
    /**
     * 参数管理 cache key
     */
    public static final String SYS_CONFIG_KEY = "sys_config:";
    @Autowired
    private RedisCache redisCache;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        loadingConfigCache();
    }

    @Override
    protected QueryWrapper<SysConfig> generateWrapper(SysConfig query) {
        Map<String, Object> params = query.getParams();
        return new QueryWrapper<SysConfig>()
                .like(StrUtil.isNotBlank(query.getConfigName()), "config_name", query.getConfigName())
                .eq(StrUtil.isNotBlank(query.getConfigType()), "config_type", query.getConfigType())
                .like(StrUtil.isNotBlank(query.getConfigKey()), "config_key", query.getConfigKey())
                .apply(ObjectUtil.isNotEmpty(params.get("beginTime")),
                        "date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
                        params.get("beginTime"))
                .apply(ObjectUtil.isNotEmpty(params.get("endTime")),
                        "date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
                        params.get("endTime"));
    }

    @Override
    public String selectByKey(String configKey) {
        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue)) {
            return configValue;
        }
        SysConfig retConfig = selectOne(new LambdaQueryWrapper<SysConfig>() {{
            eq(SysConfig::getConfigKey, configKey);
        }});
        if (StringUtils.isNotNull(retConfig)) {
            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
            return retConfig.getConfigValue();
        }
        return StringUtils.EMPTY;
    }


    @Override
    public void loadingConfigCache() {
        List<SysConfig> configsList = mapper.selectList(null);
        for (SysConfig config : configsList) {
            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
    }

    /**
     * 清空参数缓存数据
     */
    private void clearConfigCache() {
        Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redisCache.deleteObject(keys);
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }

    @Override
    public boolean selectCaptchaEnabled() {
        String captchaEnabled = selectByKey("sys.account.captchaEnabled");
        if (StringUtils.isEmpty(captchaEnabled)) {
            return true;
        }
        return Convert.toBool(captchaEnabled);
    }

    @Override
    public boolean checkConfigKeyUnique(SysConfig config) {
        Long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
        SysConfig info = mapper.selectOne(new LambdaQueryWrapper<SysConfig>()
                .eq(SysConfig::getConfigKey, config.getConfigKey()));
        if (ObjectUtil.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return SYS_CONFIG_KEY + configKey;
    }
}
